package c16多线程;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Lock与Condition {

	public static void main(String[] args) {
		Account ac = new Account();
		AccountThread atDep = new AccountThread("存款", true, ac, 10);
		AccountThread atDraw = new AccountThread("取款", false, ac, 10);
		atDep.start();
		atDraw.start();
	}

}

//模拟银行账户
class Account {
	//余额
	private double d = 0;
	//是否已经存款
	private boolean saved = false;
	//可重入锁
	private final Lock lock = new ReentrantLock();
	private final Condition cd = lock.newCondition();

	//存款
	public void deposit(double m) {
		lock.lock();
		try {
			if (saved) {
				cd.await();
			} else {
				System.err.println(Thread.currentThread().getName() + "正在存款...");
				d += m;
				System.err.println("存款后余额为：" + d);

//				//可重入锁测试：已经加锁后可以再次加锁！
//				lock.lock();
//				try{
//					System.err.println("奖励："+1);
//					d+=1;
//					System.err.println("奖励后余额为："+d);
//				}
//				finally{
//					lock.unlock();
//				}

				saved = true;
				cd.signalAll();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	//取款
	public void draw(double m) {
		lock.lock();
		try {
			if (!saved) {
				cd.await();
			} else {
				System.err.println(Thread.currentThread().getName() + "正在取款...");
				d -= m;
				System.err.println("取款后余额为：" + d);
				saved = false;
				cd.signalAll();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}

//存款或取款
class AccountThread extends Thread {
	private boolean act = true;//true为存款
	private Account ac;
	private double d;//存款或取款的数目
	private final int loop = 20;

	public AccountThread(String s, boolean act, Account ac, double d) {
		super(s);
		this.act = act;
		this.ac = ac;
		this.d = d;
	}

	@Override
	public void run() {
		for (int i = 0; i < loop; i++) {
			if (act) {
				ac.deposit(d);
			} else {
				ac.draw(d);
			}
		}
	}
}
